package com.example.client.config;

import lombok.SneakyThrows;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

/**
 * @author
 * &#064;description  基础的 SecurityConfig 类来处理通用的安全设置，例如 CSRF 保护、跨域资源共享（CORS）等
 */
@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

    // 基础的 Spring Security 配置参考 https://docs.springjava.cn/spring-security/reference/migration-7/configuration.html
    @Bean
    @SneakyThrows
    public SecurityFilterChain securityFilterChain(HttpSecurity http) {
        // OAuth2ClientAutoConfiguration        "/oauth2/**", "/login/oauth2/code/gitee", "/**"
        http
                .authorizeHttpRequests(authorize -> authorize
                        .requestMatchers("/login/**", "/oauth2/**").permitAll()
                        .anyRequest().authenticated()
                )
                .csrf(Customizer.withDefaults())
                .rememberMe((rememberMe) -> rememberMe.userDetailsService(userDetailsService()))
                .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .formLogin(Customizer.withDefaults())
                // 使用 OAuth2 登录用户,登录页面将出现第三方授权登录选项
                .oauth2Login(Customizer.withDefaults())
                // 使用默认的 OAuth2 客户端配置
                .oauth2Client(Customizer.withDefaults());
        return http.build();
    }

    @Bean
    public UserDetailsService userDetailsService() {
        UserDetails userDetails = User.builder()
                .passwordEncoder(passwordEncoder()::encode)
                .username("user")
                .password("123456")
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(userDetails);
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

}

// 配置参考官网文档 https://docs.springjava.cn/spring-security/reference/servlet/oauth2/client/index.html
// OAuth 2.0 客户端功能为 OAuth 2.0 授权框架中定义的客户角色提供支持。允许应用程序使用 OAuth 2.0 授权服务器来获取访问令牌，而无需直接与授权服务器进行交互。
/*
    OAuth 2.0 授权类型支持如下：
    - Authorization Code
    - Refresh Token
    - Client Credentials
    - Resource Owner Password Credentials
    - JWT Bearer
    - Token Exchange
    OAuth 2.0 客户端验证支持如下：
    - JWT Bearer
    HTTP 客户端支持如下：
    - WebClient
*/